#pragma once

#include "MethodInterceptor.h"
#include <map>
#include <list>

struct Vtlb;

struct CObject
{
	Vtlb* pVtbl;
};

struct Vtlb
{
	void (__stdcall * Func00)(CObject* pObject);
	Vtlb(void (__stdcall * Func00)(CObject* pObject));
};

class IAspectManager
{
public:
	virtual void InstallAdvice(void* pObject) = 0;
	virtual void AddAdvice(IMethodInterceptorAdvice* advice) = 0;
	template<class T> T* Create()
	{
		T* obj = new T();
		InstallAdvice(obj);
		return obj;
	}
};

class CAspectInstaller: public IAspectManager
{
private:
	std::list < IMethodInterceptorAdvice* > aspects;
	std::map < CObject* ,Vtlb* > objects;
	static Vtlb aspectInstallerVtlb;
	static CAspectInstaller instance;
public:
	static CAspectInstaller* Instance();
	void AddAdvice(IMethodInterceptorAdvice* advice)
	{
		aspects.insert(aspects.begin(),advice);
	}
	void InstallAdvice(void* pObject);
private:
	CAspectInstaller();
	void static __stdcall Invoke(CObject*);
};

extern IAspectManager* gAspectManager;
